 /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mahumLogs.beans;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
import com.mahumLogs.backedbeans.Configuration;
import com.mahumLogs.backedbeans.Etudiant;
import com.mahumLogs.backedbeans.Machine;
import com.mahumLogs.backedbeans.TypeMachine;
import com.mahumLogs.utils.SSH;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.UserTransaction;
import org.primefaces.event.RowEditEvent;

/**
 *
 * @author apo
 */
@Named
@RequestScoped
public class MachineBean implements Serializable {

    private Machine machine = new Machine();
    private List<Machine> lesMachines = new ArrayList();
    private List<TypeMachine> lesTypesMachines = new ArrayList();
    private Etudiant etu = new Etudiant();
    private List<Etudiant> listeEtudiants = new ArrayList();
    private @Inject
    SessionBean sessionBean;
    private @Inject
    ConfigurationBean confBean;
    @PersistenceContext
    EntityManager em;
    @Resource
    UserTransaction tx;
    
    private @Inject ClientSSHBean clientSSH;

    @PostConstruct
    public void init() {
        if(sessionBean.getEtudiant() != null){
            Query query = em.createQuery("SELECT m FROM Machine m WHERE m.etudiant.idPersonne=:idEtudiant")
                .setParameter("idEtudiant", sessionBean.getEtudiant().getIdPersonne());
            //    Query query = em.createQuery("SELECT m FROM Machine m");
            lesMachines = query.getResultList();

            Query query2 = em.createQuery("SELECT t FROM TypeMachine t");
            lesTypesMachines = query2.getResultList();
        }
    }


    public void selectedMachine(Machine m) {
        this.machine = m;
    }


    public void supprimerMachine(Machine m) {
        Configuration dhcpIp = confBean.findByKey("DHCP_SERVER_IP");
        Configuration dhcpUser = confBean.findByKey("DHCP_SERVER_USER");
        Configuration dhcpPass = confBean.findByKey("DHCP_SERVER_PWD");
        Configuration iptablesChemin = confBean.findByKey("IPTABLES_CHEMIN");
        System.out.println("Connexion au serveur" + dhcpIp.getValeur() + " avec le user " + dhcpUser.getValeur() + " et le mdp " + dhcpPass.getValeur());
        System.out.println("Dans machinebean"+m.getIdMachine()+" "+m.getAdresseMAC());
        try {
            try {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "OK", "Suppression validée!!"));
                Configuration dhcpChemin = confBean.findByKey("DHCP_CONFIG_CHEMIN");
                try {
                    Channel chan = clientSSH.execOnDHCP("cat " + dhcpChemin.getValeur());
                    if(chan != null){
                        BufferedReader reader = new BufferedReader(new InputStreamReader(chan.getInputStream()));
                        String line = "";
                        boolean trouve = false;
                        while ((line = reader.readLine()) != null && !trouve) {
                            if (line.startsWith("host " + m.getEtudiant().getIdPersonne() + "_" + m.getNumero() + " {")) {
                                System.out.println("Host réservé trouvé:" + m.getEtudiant().getIdPersonne() + "_" + m.getNumero());
                                trouve = true;

                                String cmd1 = "sed -i '/host " + m.getEtudiant().getIdPersonne()
                                        + "_"
                                        + m.getNumero() + " {/',+4d " + dhcpChemin.getValeur();
                                String cmd2 = "sed -i '/$ipt -A FORWARD -m mac --mac-source " + m.getAdresseMAC() + " -s " + m.getIp() + " -j ACCEPT/',+1d " + iptablesChemin.getValeur();

                                this.clientSSH.execOnDHCP(cmd1 + ";" + cmd2);
                                tx.begin();
                                em.remove(em.merge(m));
                                tx.commit();
                            }
                        }
                        if (!trouve) {
                            System.err.println("Host réservé non trouvé: " + m.getEtudiant().getIdPersonne() + "_" + m.getNumero());
                        }
                        chan.disconnect();
                        reader.close();
                    }
                } catch (IOException ex) {
                    Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
                }
            } catch (Exception ex) {
                System.out.println(ex);
            }
            init();
        } catch (Exception ex) {
            System.out.println("erreur de connexion au serveur");
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de connexion au serveur DHCP", "Contactez votre administrateur réseau !!"));
            Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public boolean lireConfDHCP() {
        Configuration dhcpChemin = confBean.findByKey("DHCP_CONFIG_CHEMIN");
        System.out.println("Connexion au serveur DHCP");
        try {
            try {
                Channel chan = this.clientSSH.execOnDHCP("cat " + dhcpChemin.getValeur());
                BufferedReader reader = new BufferedReader(new InputStreamReader(chan.getInputStream()));
                String line = "";
                boolean trouve = false;
                while ((line = reader.readLine()) != null && !trouve) {
                    if (line.startsWith("#MAHUMLOGS")) {
                        System.out.println("#MAHUMLOGS trouvé");
                        trouve = true;
                    }
                }
                if (!trouve) {
                    System.err.println("#MAHUMLOGS non trouvé");
                    ajouterBaliseDhcp();
                }
                reader.close();
                chan.disconnect();
            } catch (IOException ex) {
                Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
            }
            return true;
        } catch (Exception ex) {
            System.out.println("erreur de connexion au serveur");
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "erreur de connexion au serveur DHCP", "Contactez votre administrateur réseau !!"));
            return false;
        }
    }

    public boolean lireConfIptables() {
        Configuration iptablesChemin = confBean.findByKey("IPTABLES_CHEMIN");
        System.out.println("Connexion au serveur FIREWALL");
        try {
            try {
                Channel chan = this.clientSSH.execOnFirewall("cat " + iptablesChemin.getValeur());
                BufferedReader reader = new BufferedReader(new InputStreamReader(chan.getInputStream()));
                String line = "";
                boolean trouve = false;
                while ((line = reader.readLine()) != null && !trouve) {
                    if (line.startsWith("#PLAGEMAC")) {
                        System.out.println("#PLAGEMAC trouvé");
                        trouve = true;
                    }
                }
                if (!trouve) {
                    System.err.println("#PLAGEMAC non trouvé");
                    ajouterBaliseIptables();
                } 
                reader.close();
                chan.disconnect();
            } catch (IOException ex) {
                Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
            }
            return true;
        } catch (Exception ex) {
            System.out.println("erreur de connexion au serveur");
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "erreur de connexion au serveur DHCP", "Contactez votre administrateur réseau !!"));
            return false;
        }
    }

    public void ajouterBaliseDhcp() {
        try {
            Configuration dhcpChemin = confBean.findByKey("DHCP_CONFIG_CHEMIN");
            this.clientSSH.execOnDHCP("echo \"\n\n#MAHUMLOGS\" >>" + dhcpChemin.getValeur());
            System.out.println("Commentaire #MAHUMLOGS ajouté");
        } catch (Exception ex) {
            Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void ajouterBaliseIptables() {

        try {
            Configuration iptablesChemin = confBean.findByKey("IPTABLES_CHEMIN");
            this.clientSSH.execOnFirewall("echo \"\n\n#PLAGEMAC\" >>" + iptablesChemin.getValeur());
            System.out.println("Commentaire #PLAGEMAC ajouté");
        } catch (Exception ex) {
            Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void ajouterMachine() {
        if (lireConfIptables() == true) {
            if (lireConfDHCP() == true) {
                Etudiant e = this.sessionBean.getEtudiant();
                this.machine.setEtudiant(e);

                Configuration dhcpChemin = confBean.findByKey("DHCP_CONFIG_CHEMIN");
                Configuration iptablesChemin = confBean.findByKey("IPTABLES_CHEMIN");

                boolean regex = this.machine.getAdresseMAC().matches("([0-9a-fA-F]{2}[:-]){5}([0-9a-fA-F]{2})");
                if (regex == true) {

                    //test si adresse ip présente dans base
                    Query query = em.createQuery("SELECT m FROM Machine m WHERE m.etudiant.idPersonne=:idEtudiant")
                            .setParameter("idEtudiant", sessionBean.getEtudiant().getIdPersonne());
                    try {
                        List<Machine> machines = query.getResultList();
                        boolean trouvePosition = false;
                        if (machines.size() < 254) {
                            this.machine.setNumero(1);
                            for (int i = 1; i < 255 && !trouvePosition; i++) {
                                for (Machine m : machines) {
                                    if (m.getNumero() == i) {
                                        trouvePosition = false;
                                        break;
                                    } else {
                                        trouvePosition = true;
                                    }
                                }

                                if (trouvePosition) {
                                    System.out.println("Attribution de la valeur " + i);
                                    this.machine.setNumero(i);
                                }
                            }

                            this.machine.setIp(e.getIpMask() + "." + this.machine.getNumero());

                            try {
                                //Verif de l'adresse mac dans le dhcp
                                Channel chan = this.clientSSH.execOnDHCP("cat " + dhcpChemin.getValeur());
                                BufferedReader reader = new BufferedReader(new InputStreamReader(chan.getInputStream()));
                                String line = "";
                                boolean trouve = false;
                                while ((line = reader.readLine()) != null && !trouve) {
                                    if (line.startsWith("\thardware ethernet " + this.machine.getAdresseMAC())) {
                                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Cette adresse MAC est déjà dans le dhcp"));
                                                                                
                                        trouve = true;
                                    }
                                }
                                //si l'adresse mac n'est pas trouvé on inserer en base et dans le dhcp
                                if (!trouve) {
                                    System.out.println("Cette adresse MAC n'est pas dans le dhcp");

                                    System.out.println("Ajout de la machine " + this.machine.getNumero());
                                    Machine machineAdd;
                                    tx.begin();
                                    machineAdd = em.merge(this.machine);
                                    tx.commit();

                                    tx.begin();
                                    em.refresh(em.find(Machine.class, machineAdd.getIdMachine()));
                                    tx.commit();

                                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "OK", "Ajout validé"));
                                    init();

                                    try {
                                        String regle1 = "$ipt -A FORWARD -m mac --mac-source "
                                                + this.machine.getAdresseMAC() + " -s "
                                                + this.machine.getIp() + " -j ACCEPT";

                                        String regle2 = "$ipt -A FORWARD -d " + this.machine.getIp() + " -j ACCEPT";

                                        String cmd1 = "echo \"\nhost " + sessionBean.getEtudiant().getIdPersonne()
                                                + "_" + this.machine.getNumero()
                                                + " {\n\thardware ethernet " + this.machine.getAdresseMAC()
                                                + ";\n\tfixed-address " + this.machine.getIp()
                                                + ";\n}\" >>" + dhcpChemin.getValeur();
                                        String cmd2 = "/etc/init.d/isc-dhcp-server restart";
                                        String cmd3 = "sed -i '/#PLAGEMAC/a" + regle1 + "' " + iptablesChemin.getValeur();
                                        String cmd4 = "sed -i '/" + regle1 + "/a" + regle2 + "' " + iptablesChemin.getValeur();
                                        String cmd5 = "/etc/init.d/firewall restart";
                                        //Ajout de la machine dans le dhcp.conf + reload
                                        this.clientSSH.execOnDHCP(cmd1 + ";" + cmd2 + ";" + cmd3 + ";" + cmd4 + ";" + cmd5);

                                        System.out.println("La machine avec l'ip: " + sessionBean.getEtudiant().getIpMask() + "." + this.machine.getNumero() + " a été ajouté au dhcp et IPables");
                                    } catch (Exception ex) {
                                        Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
                                    }
                                }
                                reader.close();
                                chan.disconnect();
                            } catch (Exception ex) {
                                Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        } else {
                            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Vos 254 adresses sont utilisées"));
                        }
                    } catch (Exception ex) {
                        Logger.getLogger(MachineBean.class.getName()).log(Level.SEVERE, null, ex);
                    }
                } else {
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Adresse MAC non valide"));
                }
            }
        }
    }

    public Machine getMachine() {
        return machine;
    }

    public List<Machine> getLesMachines() {
        return lesMachines;
    }

    public List<TypeMachine> getLesTypesMachines() {
        return lesTypesMachines;
    }

    public void setMachine(Machine machine) {
        this.machine = machine;
    }

    public void setLesMachines(List<Machine> lesMachines) {
        this.lesMachines = lesMachines;
    }

    public void setLesTypesMachines(List<TypeMachine> lesTypesMachines) {
        this.lesTypesMachines = lesTypesMachines;
    }
}
